package com.hgyc.mom.mes.websocket.util;

import jakarta.websocket.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * WebSocket 在线用户管理工具
 * 仅限服务端管理Session映射，线程安全
 */
public class WebSocketUsers {

    private static final Logger LOGGER = LoggerFactory.getLogger(WebSocketUsers.class);
    private static final String LOG_PREFIX = "[WebSocketUsers] ";

    /**
     * 用户唯一标识 -> Session
     */
    private static final Map<String, Session> USERS = new ConcurrentHashMap<>();

    /**
     * Session -> 用户唯一标识
     */
    private static final Map<Session, String> SESSION_TO_KEY = new ConcurrentHashMap<>();

    private static ApplicationContext applicationContext;

    public static void setApplicationContext(ApplicationContext context) {
        applicationContext = context;
    }

    public static String getKeyBySession(Session session) {
        if (session == null) return null;
        return SESSION_TO_KEY.get(session);
    }

    /**
     * 新增用户
     *
     * @param key 唯一标识
     * @param session 会话对象
     */
    public static void put(String key, Session session) {
        if (key == null || session == null) return;
        USERS.put(key, session);
        SESSION_TO_KEY.put(session, key);
        LOGGER.info("{} 新用户上线：key={}, sessionId={}", LOG_PREFIX, key, session.getId());
    }

    /**
     * 根据 Session 移除用户
     *
     * @param session 会话对象
     * @return 是否移除成功
     */
    public static boolean remove(Session session) {
        if (session == null) return false;
        String key = SESSION_TO_KEY.remove(session);
        if (key != null) {
            USERS.remove(key);
            closeSession(session);
            LOGGER.info("{} 用户下线：key={}, sessionId={}", LOG_PREFIX, key, session.getId());
            return true;
        }
        return false;
    }

    /**
     * 根据 Key 移除用户
     *
     * @param key 用户唯一标识
     * @return 是否移除成功
     */
    public static boolean remove(String key) {
        if (key == null) return false;
        Session session = USERS.remove(key);
        if (session != null) {
            SESSION_TO_KEY.remove(session);
            closeSession(session);
            LOGGER.info("{} 用户下线：key={}, sessionId={}", LOG_PREFIX, key, session.getId());
            return true;
        }
        return false;
    }

    /**
     * 关闭会话
     *
     * @param session 会话对象
     */
    private static void closeSession(Session session) {
        if (session == null) return;
        try {
            if (session.isOpen()) {
                session.close();
            }
        } catch (IOException e) {
            LOGGER.warn("{} 关闭Session失败：sessionId={}", LOG_PREFIX, session.getId(), e);
        }
    }

    /**
     * 获取当前在线用户快照
     *
     * @return 不可修改集合
     */
    public static Map<String, Session> getUsers() {
        return Collections.unmodifiableMap(USERS);
    }

    /**
     * 群发文本消息
     *
     * @param message 消息内容
     */
    public static void sendMessageToAll(String message) {
        if (message == null) return;
        USERS.values().stream().toList().forEach(session -> sendMessage(session, message));
    }

    /**
     * 给指定用户发送消息
     *
     * @param key 用户唯一标识
     * @param message 消息内容
     */
    public static void sendMessageToUser(String key, String message) {
        if (key == null || message == null) return;
        Session session = USERS.get(key);
        sendMessage(session, message);
    }

    /**
     * 发送消息（单用户）
     *
     * @param session 会话对象
     * @param message 消息内容
     */
    public static void sendMessage(Session session, String message) {
        if (session == null || !session.isOpen()) {
            LOGGER.warn("{} 发送失败，连接不存在或已关闭", LOG_PREFIX);
            return;
        }
        try {
            session.getBasicRemote().sendText(message);
        } catch (IOException e) {
            LOGGER.error("{} 发送失败，清理无效连接：sessionId={}", LOG_PREFIX, session.getId(), e);
            remove(session);
        }
    }

    /**
     * 判断用户是否在线
     *
     * @param key 用户唯一标识
     * @return 是否在线
     */
    public static boolean contains(String key) {
        return key != null && USERS.containsKey(key);
    }
}
